/**
 * 微信摇一摇
 * 基础功能：
 * /lucky 只有一个抽奖接口
 */
package main

import (
	"fmt"
	"github.com/kataras/iris"
	"github.com/kataras/iris/mvc"
	"log"
	"math/rand"
	"os"
	"sync"
	"time"
)

// 奖品类型，枚举值 iota 从0开始
const (
	giftTypeCoin      = iota // 虚拟币
	giftTypeCoupon           // 不同的券
	giftTypeCouponFix        // 相同的券
	giftTypeRealSmall        // 实物小奖
	giftTypeRealLarge        // 实物大奖
)

type gift struct {
	Id       int      // 奖品ID
	Name     string   // 奖品名称
	Pic      string   // 奖品图片
	Link     string   // 奖品链接
	Type     int      // 奖品类型
	Data     string   // 奖品数据(特定的配置信息)
	DataList []string // 奖品数据集合（不同的优惠券的编码）
	Total    int      // 总数,0 不限量
	Left     int      // 剩余数
	Inuse    bool     // 是否使用中
	Rate     int      // 中奖概率，万分之N。0-9999
	RateMin  int      // 大于等于最小中奖编码
	RateMax  int      // 小于等于最大中奖编码
}

const (
	// 最大的中奖号码
	rateMax = 10000
)

var (
	logger *log.Logger

	// 奖品列表
	giftList []*gift

	mu sync.Mutex
)

type lotteryController struct {
}

// 初始化日志
func initLog() {
	f, _ := os.Create("C:\\Users\\Administrator\\Desktop\\log\\lottery_demo.log")
	logger = log.New(f, "", log.Ldate|log.Lmicroseconds)
}

// 初始化奖品列表
func initGift() {
	giftList = make([]*gift, 5)
	g1 := gift{
		Id:       1,
		Name:     "手机大奖",
		Pic:      "",
		Link:     "",
		Type:     giftTypeRealLarge,
		Data:     "",
		DataList: nil,
		Total:    2,
		Left:     2,
		Inuse:    true,
		Rate:     10,
		RateMin:  0,
		RateMax:  0,
	}
	giftList[0] = &g1

	g2 := gift{
		Id:       2,
		Name:     "充电器",
		Pic:      "",
		Link:     "",
		Type:     giftTypeRealSmall,
		Data:     "",
		DataList: nil,
		Total:    10,
		Left:     10,
		Inuse:    true,
		Rate:     100,
		RateMin:  0,
		RateMax:  0,
	}
	giftList[1] = &g2

	g3 := gift{
		Id:       3,
		Name:     "优惠券满200减50元",
		Pic:      "",
		Link:     "",
		Type:     giftTypeCouponFix,
		Data:     "mall-coupon-2020",
		DataList: nil,
		Total:    50,
		Left:     50,
		Inuse:    true,
		Rate:     500,
		RateMin:  0,
		RateMax:  0,
	}
	giftList[2] = &g3

	g4 := gift{
		Id:       4,
		Name:     "直降优惠券50元",
		Pic:      "",
		Link:     "",
		Type:     giftTypeCoupon,
		Data:     "",
		DataList: []string{"c01", "c02", "c03", "c04", "c05", "c06", "c07", "c08", "c09", "c10"},
		Total:    10,
		Left:     10,
		Inuse:    true,
		Rate:     800,
		RateMin:  0,
		RateMax:  0,
	}
	giftList[3] = &g4

	g5 := gift{
		Id:       5,
		Name:     "金币",
		Pic:      "",
		Link:     "",
		Type:     giftTypeCoin,
		Data:     "10金币",
		DataList: nil,
		Total:    5,
		Left:     5,
		Inuse:    true,
		Rate:     5000,
		RateMin:  0,
		RateMax:  0,
	}
	giftList[4] = &g5

	// 整理中间区间数据
	rateStart := 0

	for _, data := range giftList {
		if !data.Inuse {
			continue
		}

		data.RateMin = rateStart
		data.RateMax = rateStart + data.Rate

		if data.RateMax >= rateMax {
			data.RateMax = rateMax
			rateStart = 0
		} else {
			rateStart += data.Rate
		}
	}
}

func newApp() (app *iris.Application) {
	app = iris.New()
	mvc.New(app.Party("/")).Handle(&lotteryController{})

	initLog()

	initGift()

	return app
}

func main() {
	var (
		app *iris.Application
	)

	app = newApp()
	_ = app.Run(iris.Addr(":8080"))
}

// 奖品数量的信息
func (c *lotteryController) Get() string {
	var (
		count = 0
		total = 0
		data  *gift
	)

	for _, data = range giftList {
		if data.Inuse && (data.Total == 0 || (data.Total > 0 && data.Left > 0)) {
			count++
			total += data.Left
		}
	}

	return fmt.Sprintf("当前有效奖品种类数量：%d，限量奖品总数量为：%d\n", count, total)
}
func (c *lotteryController) GetLucky() (result map[string]interface{}) {

	var (
		code     int32
		ok       bool
		data     *gift
		sendData string
	)

	mu.Lock()
	defer mu.Unlock()
	code = luckyCode()

	result = make(map[string]interface{})
	result["success"] = ok

	for _, data = range giftList {
		if !data.Inuse || (data.Total > 0 && data.Left <= 0) {
			continue
		}

		if data.RateMin <= int(code) && data.RateMax > int(code) {
			// 中奖了，抽奖编码在奖品编码范围内
			// 开始发奖
			switch data.Type {
			case giftTypeCoin:
				ok, sendData = sendCoin(data)
			case giftTypeCoupon:
				ok, sendData = sendCoupon(data)
			case giftTypeCouponFix:
				ok, sendData = sendCouponFix(data)
			case giftTypeRealSmall:
				ok, sendData = sendRealSmall(data)
			case giftTypeRealLarge:
				ok, sendData = sendRealLarge(data)
			}

			if ok {
				// 中奖后，成功得到产品
				// 生成中奖纪录
				saveLuckData(code, data.Id, data.Name, data.Link, sendData, data.Left)
				result["success"] = ok
				result["id"] = data.Id
				result["name"] = data.Name
				result["link"] = data.Link
				result["data"] = sendData
				break
			}
		}
	}
	return
}

func luckyCode() (code int32) {
	var (
		seed int64
	)
	seed = time.Now().UnixNano()
	code = rand.New(rand.NewSource(seed)).Int31n(int32(rateMax))
	return
}

// 虚拟币
func sendCoin(data *gift) (bool, string) {
	if data.Total == 0 {
		// 数量无限
		return true, data.Data
	} else if data.Left > 0 {
		// 还有剩余
		data.Left = data.Left - 1
		return true, data.Data
	} else {
		return false, "奖品已发完"
	}
}

// 不同值的优惠券
func sendCoupon(data *gift) (bool, string) {
	var (
		left int
	)

	if data.Left > 0 {
		// 还有剩余
		left = data.Left - 1
		data.Left = left
		return true, data.DataList[left]
	} else {
		return false, "奖品已发完"
	}
}

// 固定的优惠券
func sendCouponFix(data *gift) (bool, string) {
	if data.Total == 0 {
		// 数量无限
		return true, data.Data
	} else if data.Left > 0 {
		// 还有剩余
		data.Left = data.Left - 1
		return true, data.Data
	} else {
		return false, "奖品已发完"
	}
}

func sendRealSmall(data *gift) (bool, string) {
	if data.Total == 0 {
		// 数量无限
		return true, data.Data
	} else if data.Left > 0 {
		// 还有剩余
		data.Left = data.Left - 1
		return true, data.Data
	} else {
		return false, "奖品已发完"
	}
}

func sendRealLarge(data *gift) (bool, string) {
	if data.Total == 0 {
		// 数量无限
		return true, data.Data
	} else if data.Left > 0 {
		// 还有剩余
		data.Left = data.Left - 1
		return true, data.Data
	} else {
		return false, "奖品已发完"
	}
}

// 纪录用户的获奖信息
func saveLuckData(code int32, id int, name string, link string, sendData string, left int) {
	logger.Printf("lucky, code=%d, gift=%d, name=%s, link=%s, data=%s, left=%d \n", code, id, name, link, sendData, left)
}
